#include <windows.h>
#include <stdio.h>


#define COLOR_RGBTO555(r,g,b) ((unsigned short)(((b>>3)<<10) | ((g>>3)<<5) | (r>>3)))

typedef enum
{
	FORMAT_UNKNOWN = 0,
	FORMAT_BMP
}EFileFormat;

typedef enum
{
	GX_TEXFMT_NONE = 0,
	GX_TEXFMT_A3I5 = 1,
	GX_TEXFMT_PLTT4 = 2,
	GX_TEXFMT_PLTT16 = 3,
	GX_TEXFMT_PLTT256 = 4,
	GX_TEXFMT_COMP4x4 = 5,
	GX_TEXFMT_A5I3 = 6,
	GX_TEXFMT_DIRECT = 7
}
GXTexFmt;

typedef enum
{
	GX_TEXGEN_NONE = 0,
	GX_TEXGEN_TEXCOORD = 1,
	GX_TEXGEN_NORMAL = 2,
	GX_TEXGEN_VERTEX = 3
}
GXTexGen;

typedef enum
{
	GX_TEXSIZE_S8 = 0,
	GX_TEXSIZE_S16 = 1,
	GX_TEXSIZE_S32 = 2,
	GX_TEXSIZE_S64 = 3,
	GX_TEXSIZE_S128 = 4,
	GX_TEXSIZE_S256 = 5,
	GX_TEXSIZE_S512 = 6,
	GX_TEXSIZE_S1024 = 7
}
GXTexSizeS;

typedef enum
{
	GX_TEXSIZE_T8 = 0,
	GX_TEXSIZE_T16 = 1,
	GX_TEXSIZE_T32 = 2,
	GX_TEXSIZE_T64 = 3,
	GX_TEXSIZE_T128 = 4,
	GX_TEXSIZE_T256 = 5,
	GX_TEXSIZE_T512 = 6,
	GX_TEXSIZE_T1024 = 7
}
GXTexSizeT;

typedef enum
{
	GX_TEXREPEAT_NONE = 0,
	GX_TEXREPEAT_S = 1,
	GX_TEXREPEAT_T = 2,
	GX_TEXREPEAT_ST = 3
}
GXTexRepeat;

typedef enum
{
	GX_TEXFLIP_NONE = 0,
	GX_TEXFLIP_S = 1,
	GX_TEXFLIP_T = 2,
	GX_TEXFLIP_ST = 3
}
GXTexFlip;

typedef enum
{
	GX_TEXPLTTCOLOR0_USE = 0,
	GX_TEXPLTTCOLOR0_TRNS = 1
}
GXTexPlttColor0;

typedef unsigned short u16;

#pragma pack(1)
typedef struct  
{
	u16	signature;		//should be 0x5854
	u16	palSize;		//how many colors are in the palette
	u16	tex_repeat:2;
	u16	tex_flip:2;
	u16	tex_sizeS:3;
	u16	tex_sizeT:3;
	u16	tex_format:3;
	u16	tex_use0:1;
	u16	tex_coord:2;
}TTexHeader;
#pragma pack()

bool showHelp = FALSE;

TTexHeader texHeader;

char *in_name = NULL;
char *out_name = NULL;

FILE *fin = NULL;
FILE *fout = NULL;


bool processBitmap()
{
	BITMAPFILEHEADER bmpHdr;
	BITMAPINFOHEADER bmpInfo;
	int powers[] = {8,16,32,64,128,256,512,1024};

	fread(&bmpHdr, sizeof(bmpHdr), 1, fin);
	fread(&bmpInfo, sizeof(bmpInfo), 1, fin);

	if (bmpHdr.bfType != 0x4D42)
	{
		printf("Invalid bitmap file\n");
		return false;
	}
	if (bmpInfo.biCompression != 0)
	{
		printf("Can't read compressed images\n");
		return false;
	}


	int sz_s = -1;
	int sz_t = -1;
	for (int i=0;i<8;i++)
	{
		if (bmpInfo.biWidth == powers[i])
			sz_s = i;
		if (bmpInfo.biHeight == powers[i])
			sz_t = i;
	}

	if ((sz_s == -1) || (sz_t == -1))
	{
		printf("Image dimensions must be power of two in the interval [8 , 1024] \n");
		return false;
	}

	texHeader.tex_sizeS = sz_s;
	texHeader.tex_sizeT = sz_t;

	texHeader.palSize = bmpInfo.biClrUsed;
	
	fwrite(&texHeader, sizeof(texHeader), 1, fout);
	
	int palette[256];
	short pal[256];

	fread(palette, 4 * bmpInfo.biClrUsed, 1, fin);

	for (int i=0;i<bmpInfo.biClrUsed;i++)
	{
		pal[i] = COLOR_RGBTO555(
			(palette[i] & 0x00ff0000)>>16,
			(palette[i] & 0x0000ff00)>>8,
			(palette[i] & 0x000000ff));
	}

	fwrite(pal, bmpInfo.biClrUsed * 2, 1, fout);

	int sz = bmpInfo.biWidth * bmpInfo.biHeight;
	char *data = new char[sz];
	fread(data, sz,1,fin);
	fwrite(data, sz, 1, fout);

	fclose(fout);
	
	return true;
}

void usage()
{
	printf("Texture converting utility\n");
	printf("makeTex [options] <input_file> <output_file>\n\n");
	printf("where options can be:\n");
	printf("\n(c) Fili 2007\n\n");
}

int main(int argc, char **argv)
{
	texHeader.signature		= 0x5854;
	texHeader.palSize		= 256;

	texHeader.tex_repeat	= GX_TEXREPEAT_ST;
	texHeader.tex_flip		= GX_TEXFLIP_NONE;
	texHeader.tex_sizeS		= GX_TEXSIZE_S8;
	texHeader.tex_sizeT		= GX_TEXSIZE_T8;
	texHeader.tex_format	= GX_TEXFMT_PLTT256;
	texHeader.tex_use0		= GX_TEXPLTTCOLOR0_USE;
	texHeader.tex_coord		= GX_TEXGEN_TEXCOORD;

	for (int i=1;i<argc;i++)
	{
		if (argv[i][0] == '-')
		{
		}
		else
		{
			if (in_name != NULL)
			{
				out_name = argv[i];
			}
			else
				in_name = argv[i];
		}
	}

	if ((argc <= 1) || showHelp)
	{
		usage();
		return 0;
	}

	if (in_name == NULL)
	{
		printf("You must specify input name\n");
		return 1;
	}

	if (out_name == NULL)
	{
		printf("You must specify output name\n");
		return 1;
	}

	EFileFormat format = FORMAT_UNKNOWN;

	int len = strlen(in_name);
	if (len>4)
	{
		char *ext = &in_name[len-4];
		if (!stricmp(ext,".BMP"))
			format = FORMAT_BMP;
	}

	if (format == FORMAT_UNKNOWN)
	{
		printf("Unknown texture extension\n");
		return 1;
	}

	fin = fopen(in_name, "rb");
	if (!fin)
	{
		printf("Can't open file %s for reading\n", in_name);
		return 1;
	}

	fout = fopen(out_name, "wb");
	if (!fout)
	{
		printf("Can't open file %s for writing\n", out_name);
		return 1;
	}
	
	printf("Processing texture %s -> %s\n",in_name, out_name);

	bool success = FALSE;

	switch (format)
	{
	case FORMAT_BMP:
		success = processBitmap();
		break;
	}

	fclose(fin);
	fclose(fout);

	if (!success)
		return 1;

	return 0;
}